#ifndef S21_CONTAINER_STACK_H_
#define S21_CONTAINER_STACK_H_

#include <initializer_list>

#include "../vector/s21_vector.h"

namespace s21 {

template <typename T>
class stack {
 public:
  using value_type = T;
  using reference = value_type&;
  using rv_reference = value_type&&;
  using const_reference = const value_type&;
  using size_type = std::size_t;

  stack() {}

  stack(std::initializer_list<value_type> const& items) : data_(items) {}

  stack(const stack& other) : data_(other.data_) {}

  stack(stack&& other) noexcept : data_(std::move(other.data_)) {}

  ~stack() = default;

  stack& operator=(const stack& other) {
    data_ = other.data_;

    return *this;
  }

  stack& operator=(stack&& other) noexcept {
    data_ = std::move(other.data_);

    return *this;
  }

  const_reference top() const { return data_.back(); }

  reference top() { return data_[size() - 1]; }

  bool empty() const { return data_.empty(); }

  size_type size() const { return data_.size(); }

  void push(const_reference value) { data_.push_back(value); }

  void push(rv_reference value) { data_.push_back(std::move(value)); }

  void pop() { data_.pop_back(); }

  void clear() { data_.clear(); }

  void swap(stack& other) noexcept { std::swap(data_, other.data_); }

  template <typename... Args>
  void insert_many_front(Args&&... args) {
    data_.insert_many_back(std::forward<Args>(args)...);
  }

 private:
  vector<value_type> data_;
};
}  // namespace s21
#endif  // S21_CONTAINER_STACK_H_
